package com.ibm.crl.sb.thread.typicalexam.philosophers;

/**
 * 哲学家进餐问题
 * 
 * @author soft
 * 
 */
class Thinker extends Thread {
	// 布尔数组，接受main线程传来的数组，用以表示筷子是否被占用
	private boolean[] chopsticks;
	// 哲学家号，方便后面得到他旁边的两根筷子
	private int thinkerindex;

	// 唯一的构造函数
	public Thinker(boolean[] chopsticks, int thinkerindex) {
		this.chopsticks = chopsticks;
		this.thinkerindex = thinkerindex;
	}

	// 重载run函数
	public void run() {
		// 一日三餐，这里只设置三次循环表示一下，没抢到筷子就没办法
		for (int i = 0; i < 3; i++) { // 如果哲学家旁边的两根筷子都空闲
			if (chopsticks[thinkerindex] == false
					&& chopsticks[(thinkerindex + 1) % 5] == false) {
				// 占用这两根筷子
				// 此处注意，很有可能有哲学家已经拿起了这两根筷子但是还没有开始进餐
				// 可其它线程获得了CPU，旁边的哲学家也不能拿起筷子进餐
				chopsticks[thinkerindex] = true;
				chopsticks[(thinkerindex + 1) % 5] = true;
				System.out.println("哲学家" + thinkerindex + "开始进餐");

				// 进餐过程，用时200毫秒表示一下
				try {
					this.sleep(200);
				} catch (Exception e) {
				}
				// 进餐完毕，放下这两根筷子
				chopsticks[thinkerindex] = false;
				chopsticks[(thinkerindex + 1) % 5] = false;
				System.out.println("哲学家" + thinkerindex + "进餐完毕");
			} else {
				// 只要筷子被占用了，就不能进餐，不一定旁边有人正在进餐
				System.out.println("哲学家" + thinkerindex + "没拿到筷子，不可以进餐");
			}
		}
	}

	public static void main(String[] args) {
		// 初始化布尔数组，默认值为false，代表筷子空闲
		boolean[] chopsticks = new boolean[5];

		// 数组是引用变量，传入地址，各线程共享该数组
		Thinker t0 = new Thinker(chopsticks, 0);
		Thinker t1 = new Thinker(chopsticks, 1);
		Thinker t2 = new Thinker(chopsticks, 2);
		Thinker t3 = new Thinker(chopsticks, 3);
		Thinker t4 = new Thinker(chopsticks, 4);

		t0.start();
		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}